package com.ybt.communicate.tcp.server;

import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;

import org.apache.log4j.Logger;

import com.ruleengine.context.IWorkflowConext;
import com.ybt.communicate.core.IConnection;
import com.ybt.communicate.core.callback.IConnectionCallback;
import com.ybt.communicate.core.exception.ProtocolException;
import com.ybt.communicate.tcp.configration.TCPConstants;
import com.ybt.communicate.tcp.configration.TCPRuntimeConfig;

public class TCPServerShortConnection implements IConnection {
    private static Logger logger = Logger
            .getLogger(TCPServerShortConnection.class);
    private Socket socket;
    private TCPRuntimeConfig config;

    public TCPServerShortConnection(Socket socket, TCPRuntimeConfig config) {
        super();
        this.socket = socket;
        this.config = config;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.ybt.communicate.core.IConnection#receive()
     */
    public Object receive() throws ProtocolException {
        // TODO Auto-generated method stub
        // 读取数据
        try {
            logger.debug("begin to receive data from "
                    + socket.getRemoteSocketAddress());
            InputStream in = socket.getInputStream();
            ReadableByteChannel channel = Channels.newChannel(in);
            byte[] contents = config.getReadAccessor().receive(channel);
            if(TCPConstants.TO_STRING.equals(config.getStaticConfig().getCommonConfig().getAction())){
                //将byte转换成string
                String encode = config.getStaticConfig().getCommonConfig().getEncode();
                String result = null;
                if(encode==null){
                    //使用平台默认编码
                    result =  new String(contents);
                }else{
                    //使用自定义编码
                    result =  new String(contents, encode);
                }
                logger.debug(result);
                
                return result;
            }
            return contents;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            throw new ProtocolException(e);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.ybt.communicate.core.IConnection#send(com.ruleengine.context.IWorkflowConext,
     *      java.lang.Object)
     */
    public Object send(IWorkflowConext context, Object data)
            throws ProtocolException {
        // TODO Auto-generated method stub
        if (!config.isDuplex()) {
            // 单通道，server端协议不支持发送
            throw new ProtocolException("unsupport method for "
                    + config.getProtocolType() + ", protocol id ["
                    + config.getProtocolId() + "]");
        }
        try {
            // 发送数据
            logger.debug("begin to send data to "
                    + socket.getRemoteSocketAddress());
            WritableByteChannel channelOut = Channels.newChannel(socket
                    .getOutputStream());
            byte[] contents = null;
            if(data instanceof String){
                String encode = config.getStaticConfig().getCommonConfig().getEncode();
                if(encode==null){
                    //使用平台默认编码
                    contents =  ((String)data).getBytes();
                }else{
                    //使用自定义编码
                    contents =  ((String)data).getBytes(encode);
                }
            }else if(data instanceof byte[]){
                contents = (byte[])data;
            }else{
                throw new ProtocolException("unsupport parameter type of data to client " + data);
            }
            config.getWriteAccessor().send(channelOut, contents);
            
            logger.debug("send "+contents.length+" bytes to "
                    + socket.getRemoteSocketAddress()+" successfully");
        } catch (IOException e) {
            throw new ProtocolException("send data to client "
                    + config.getPort() + " error ", e);
        }finally{
            //短连接，所以TCP server发送完数据后，直接关闭即可。 
            close();
        }
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.ybt.communicate.core.IConnection#sendNonBlocking(com.ruleengine.context.IWorkflowConext,
     *      java.lang.Object,
     *      com.ybt.communicate.core.callback.IConnectionCallback)
     */
    public void sendNonBlocking(IWorkflowConext context, Object data,
            IConnectionCallback callBack) throws ProtocolException {
        // TODO Auto-generated method stub
        throw new ProtocolException("unsupport method for "
                + config.getProtocolType() + ", protocol id ["
                + config.getProtocolId() + "]");
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.ybt.communicate.core.IConnection#close()
     */
    public void close() throws ProtocolException {
        // TODO Auto-generated method stub
        try {
            if (socket != null) {
                socket.close();
                socket = null;
            }
        } catch (Exception e) {
            throw new ProtocolException("close socket from client "
                    + config.getPort() + " error ", e);
        }
    }

    public String getProtocolId() {
        // TODO Auto-generated method stub
        return config.getProtocolId();
    }

}
